package scantask.client.presentationLayer;

import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.layers.AirspaceLayer;
import gov.nasa.worldwind.layers.AnnotationLayer;
import gov.nasa.worldwind.render.ScreenAnnotation;
import gov.nasa.worldwind.render.airspaces.Polygon;

import java.awt.Color;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.Map.Entry;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;

import scantask.client.domainLayer.ControllerInterface;
import scantask.containers.Area;
import scantask.containers.Coordinate;
import scantask.containers.InformationObject;
import scantask.containers.WeekDate;
import scantask.containers.exceptions.InvalidWeekNumberException;
import scantask.containers.exceptions.InvalidYearException;
import scantask.containers.exceptions.MissingLayerException;
import scantask.containers.exceptions.UnInitializeObjectException;
import scantask.server.domainLayer.Exceptions.ControllerException;
import scantask.server.domainLayer.Exceptions.LoginException;

public class HistoryPanel extends JPanel{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	// The world window of NASA.
	final private WorldWindow _wwd;
	
	// The client controller.
	private ControllerInterface _controller;
	
	// Layers for shapes.
	private Map<String, AirspaceLayer> _layers;
	
	// Layer for dates.
	private AnnotationLayer _datesLayer;
	
	// The combo box.
	final private JComboBox _yearsCombo;
	
	// The combo box.
	final private JComboBox _weeksCombo;
	// Map for years and weeks.
	private HashMap<String, HashSet<String>> _yearsToWeeks;
	
	// Last Measurement.
	private WeekDate _lastWeek;
	
	public HistoryPanel(WorldWindow wwd, ControllerInterface controller, 
			Map<String, AirspaceLayer> layers, AnnotationLayer datesLayer) {
		
		super();
		this.setLayout(null);
		this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
	
		this._wwd = wwd;
		this._controller = controller;
		this._layers = layers;
		this._datesLayer = datesLayer;
		this._yearsToWeeks = new HashMap<String, HashSet<String>>();
		
		JLabel choose = new JLabel();
		choose.setText("Choose week:");
		choose.setBounds(10, 10, 100, 25);
        this.add(choose);
        
        this._yearsCombo = new JComboBox();
        this._yearsCombo.setBounds(10, 45, 80, 25);
        this._yearsCombo.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				HistoryPanel.this._weeksCombo.removeAllItems();
				if(HistoryPanel.this._yearsCombo.getSelectedItem() != null){
					String year = HistoryPanel.this._yearsCombo.
											getSelectedItem().toString();
					Iterator<String> iter = HistoryPanel.this._yearsToWeeks.
											get(year).iterator();
					String[] weeks = new String[HistoryPanel.this._yearsToWeeks.
					                            				get(year).size()];
					int i = 0;
					while(iter.hasNext()){
						weeks[i] = iter.next()+"";
						i++;
					}
					Arrays.sort(weeks);
					String[] reverseWeeks = new String[weeks.length];
					for(i = weeks.length-1; i>=0; i--){
						reverseWeeks[weeks.length-i-1] = weeks[i];
					}
					for(i = 0; i<reverseWeeks.length; i++){
						HistoryPanel.this._weeksCombo.addItem(reverseWeeks[i]);
					}
				}
			}
		});
        this.add(this._yearsCombo);
        
        this._weeksCombo = new JComboBox();
        this._weeksCombo.setBounds(100, 45, 80, 25);
        this.add(this._weeksCombo);
        
        JButton go = new JButton("GO");
        go.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				int week = Integer.parseInt(HistoryPanel.
						this._weeksCombo.getSelectedItem()+"");
				int year = Integer.parseInt(HistoryPanel.
						this._yearsCombo.getSelectedItem()+"");
				Vector<InformationObject> objects = new Vector<InformationObject>();
				try {
					Iterator<Entry<String, AirspaceLayer>> iter = 
						HistoryPanel.this._layers.entrySet().iterator();
					while(iter.hasNext()){
						iter.next().getValue().removeAllAirspaces();
					}
					HistoryPanel.this._layers.clear();
					HistoryPanel.this.createAreasLayer();
					objects = HistoryPanel.this._controller.viewHistory(year, week);
					Set<String> types = HistoryPanel.this._controller.getDataTypes();
					Iterator<String> typesIter = types.iterator();
					while(typesIter.hasNext()){
						String type = typesIter.next(); 
						if(type.startsWith("SyntheticObject")){
							if(!HistoryPanel.this._layers.containsKey("SyntheticObject")){
								AirspaceLayer l = new AirspaceLayer();
								Presentation.insertBeforeCompass(
										HistoryPanel.this._wwd, l);
								HistoryPanel.this._layers.put("SyntheticObject", l);
							}
						}
						else{
							AirspaceLayer l = new AirspaceLayer();
							Presentation.insertBeforeCompass(
									HistoryPanel.this._wwd, l);
							HistoryPanel.this._layers.put(type, l);
						}
					}
					HistoryPanel.this._controller.
							setPolygonesLayers(HistoryPanel.this._layers);
					for(int i = 0; i<objects.size(); i++){
						objects.elementAt(i).getPolygone().draw();
					}
					String s;
					s = "Date of measurement" +
							"\nYear: " + year +
							"\nWeek: " + week;
					ScreenAnnotation a = new ScreenAnnotation(s, new Point(100, 20));
					HistoryPanel.this._datesLayer.removeAllAnnotations();
					HistoryPanel.this._datesLayer.addAnnotation(a);
					UpperPanel.updateShowHidePanel(HistoryPanel.this._layers);
					HistoryPanel.this.update();
				} catch (LoginException e) {
				} catch (InvalidWeekNumberException e) {
				} catch (InvalidYearException e) {
				} catch (UnInitializeObjectException e) {
				} catch (MissingLayerException e) {
				} catch (ControllerException e) {
				}
			}
        	
        });
        go.setBounds(10, 80, 160, 25);
        this.add(go);
        
        JButton last = new JButton("Last week");
        last.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				Vector<InformationObject> objects = new Vector<InformationObject>();
				try {
					Iterator<Entry<String, AirspaceLayer>> iter = 
						HistoryPanel.this._layers.entrySet().iterator();
					while(iter.hasNext()){
						iter.next().getValue().removeAllAirspaces();
					}
					HistoryPanel.this._layers.clear();
					HistoryPanel.this.createAreasLayer();
					objects = HistoryPanel.this._controller.viewHistory(
							HistoryPanel.this._lastWeek.getYear(),
							HistoryPanel.this._lastWeek.getWeek());
					Set<String> types = HistoryPanel.this._controller.getDataTypes();
					Iterator<String> typesIter = types.iterator();
					while(typesIter.hasNext()){
						String type = typesIter.next(); 
						if(type.startsWith("SyntheticObject")){
							if(!HistoryPanel.this._layers.containsKey("SyntheticObject")){
								AirspaceLayer l = new AirspaceLayer();
								Presentation.insertBeforeCompass(
										HistoryPanel.this._wwd, l);
								HistoryPanel.this._layers.put("SyntheticObject", l);
							}
						}
						else{
							AirspaceLayer l = new AirspaceLayer();
							Presentation.insertBeforeCompass(
									HistoryPanel.this._wwd, l);
							HistoryPanel.this._layers.put(type, l);
						}
					}
					HistoryPanel.this._controller.
							setPolygonesLayers(HistoryPanel.this._layers);
					for(int i = 0; i<objects.size(); i++){
						objects.elementAt(i).getPolygone().draw();
					}
					String s;
					s = "Date of measurement" +
							"\nYear: " + HistoryPanel.this._lastWeek.getYear() +
							"\nWeek: " + HistoryPanel.this._lastWeek.getWeek();
					ScreenAnnotation a = new ScreenAnnotation(s, new Point(100, 20));
					HistoryPanel.this._datesLayer.removeAllAnnotations();
					HistoryPanel.this._datesLayer.addAnnotation(a);
					HistoryPanel.this._yearsCombo.setSelectedIndex(0);
					HistoryPanel.this._weeksCombo.setSelectedIndex(0);
					UpperPanel.updateShowHidePanel(HistoryPanel.this._layers);
					HistoryPanel.this.update();
				} catch (LoginException e) {
				} catch (InvalidWeekNumberException e) {
				} catch (InvalidYearException e) {
				} catch (UnInitializeObjectException e) {
				} catch (MissingLayerException e) {
				} catch (ControllerException e) {
				}
			}
        });
        last.setBounds(10, 115, 160, 25);
        this.add(last);
		
	}
	
	public void updateComboBox(){
		try {
			this._yearsToWeeks = new HashMap<String, HashSet<String>>();
			this._yearsCombo.removeAllItems();
			this._weeksCombo.removeAllItems();
			Vector<WeekDate> vec = this._controller.getValidDates();
			if ( (vec != null) && (vec.size() > 0)){
				try {
					this._lastWeek = new WeekDate(
							vec.get(vec.size()-1).getWeek(),
							vec.get(vec.size()-1).getYear());
					String s;
					s = "Date of measurement" +
							"\nYear: " + this._lastWeek.getYear() +
							"\nWeek: " + this._lastWeek.getWeek();
					ScreenAnnotation a = new ScreenAnnotation(s, new Point(100, 20));
					this._datesLayer.addAnnotation(a);
				} catch (InvalidWeekNumberException e) {
				} catch (InvalidYearException e) {
				}
			}
			for (int i = 0; i<vec.size(); i++){
				if(this._yearsToWeeks.containsKey(vec.get(i).getYear()+"")){
					this._yearsToWeeks.get(vec.get(i).getYear()+"").add(
							vec.get(i).getWeek()+"");
				}
				else{
					this._yearsToWeeks.put(vec.get(i).getYear()+"", 
							new HashSet<String>());
					this._yearsToWeeks.get(vec.get(i).getYear()+"").add(
							vec.get(i).getWeek()+"");
				}
			}
			String[] yearsArray = new String[this._yearsToWeeks.keySet().size()];
			int i = 0;
			Iterator<String> years = this._yearsToWeeks.keySet().iterator();
			while(years.hasNext()){
				yearsArray[i] = years.next()+"";
				i++;
			}
			Arrays.sort(yearsArray);
			String[] reverseYears = new String[yearsArray.length];
			for(i = yearsArray.length-1; i>=0; i--){
				reverseYears[yearsArray.length-i-1] = yearsArray[i];
			}
			for(i = 0; i<reverseYears.length; i++){
				this._yearsCombo.addItem(reverseYears[i]);
			}
		} catch (LoginException e1) {
		}
	}
	
	public void createAreasLayer(){
		Vector<Area> areas;
		try {
			areas = this._controller.getUserAreas();
			AirspaceLayer areasLayer = new AirspaceLayer();
			Presentation.insertBeforeCompass(
					this._wwd, areasLayer);
			this._layers.put("Areas", areasLayer);
			for(int i = 0; i<areas.size(); i++){
				Vector<Coordinate> coors = areas.get(i).getVertixes();
				List<LatLon> coorsList = new LinkedList<LatLon>();
				String name = areas.get(i).getName();
				String type = areas.get(i).getType();
				for (int j = 0; j<coors.size(); j++){
					coorsList.add(LatLon.fromDegrees(
							coors.get(j).getY(), coors.get(j).getX()));
				}
				Polygon pol = new Polygon(coorsList);
				pol.setAltitudes(0, FunctionalityPanel.DEFAULT_AREA_HEIGHT);
				pol.setDescription("Area: " + name + "\nType: " + type);
				Presentation.AppFrame.setAreaAttr(pol, areas.get(i).getColor(), Color.BLACK);
				areasLayer.addAirspace(pol);
			}
		} catch (LoginException e) {
		} catch (UnInitializeObjectException e) {
		}
	}
	
	public void removeDatesAnnotation(){
		this._datesLayer.removeAllAnnotations();
	}
	
	// Update Globe.
    private void update()
    {
        this._wwd.redraw();
    }

}
